/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufc.quixada.adrs.comandos.admin;

import br.ufc.quixada.adrs.interfaces.Comando;
import br.ufc.quixada.adrs.model.Descarte;
import br.ufc.quixada.adrs.model.Produtor;
import br.ufc.quixada.adrs.model.QuestionarioQuantitativo;
import br.ufc.quixada.adrs.model.RelatorioDescarteResult;
import br.ufc.quixada.adrs.model.RelatorioResult;
import br.ufc.quixada.adrs.model.TipoAnimal;
import br.ufc.quixada.adrs.model.Visita;
import br.ufc.quixada.adrs.service.TipoAnimalService;
import br.ufc.quixada.adrs.util.UtilAdrs;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author ismaily
 */
public class CmdMontarRelatorioQtDescartes implements Comando {

    public String executa(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession(true);


        //definição das mensagens de erro
        String[] mensagemErro = new String[7];
        mensagemErro[1] = "Por favor, selecione um ou todos os tipos de animais";
        mensagemErro[2] = "Por favor, especifique um período para o relatório";
        mensagemErro[3] = "Por favor, verifique o preenchemento da data que indica o início do período do relatório.";
        mensagemErro[4] = "Por favor, verifique o preenchemento da data que indica o fim do período do relatório.";
        mensagemErro[5] = "Por favor, selecione um ou alguns filtros para o relatório";
        mensagemErro[6] = "Período selecionado não contem visitas";



        //Datas de inicio e fim do relatório
        Date ini = null;
        Date fim = null;

        //setar o periodo marcado, caso não seja escolhido todos os períodos
        String dataIni = request.getParameter("dataInicio");
        if (dataIni != null) {
            ini = UtilAdrs.treatToDate(dataIni);
        }
        String dataFim = request.getParameter("dataFim");
        if (dataFim != null) {
            fim = UtilAdrs.treatToDate(dataFim);
        }

        //estrutura onde será armazenado os dados dos relatórios       
        ArrayList<RelatorioDescarteResult> resultDescarte = new ArrayList<RelatorioDescarteResult>();

        //pega o tipo de animal
        String tipoAnimal = (String) request.getParameter("tipoAnimal");

        //pega os filtros marcados
        String machos = request.getParameter("machosDescartes");
        String femeas = request.getParameter("femeasDescartes");
        String exibirRelatorioDetalhadoDescartes = request.getParameter("detalharRelatorioDescartes");

        //todos os produtores selecionados
        ArrayList<Produtor> prods = (ArrayList<Produtor>) session.getAttribute("produtoresSelecionados");

        //metodo que valida os campos(se foram todos preenchido) e retorna o codigo do erro a ser exibido na tela
        int codErro = validaCampos(tipoAnimal, dataIni, dataFim, machos, femeas);
        if (codErro != 1) {
            session.setAttribute("erro", mensagemErro[codErro * (-1)]);
            return "/admin/admin_monta_relatorio_qt_passo_quatro.jsp";
        }


        //se não houver visita retornamos com a mensagem 6(ver acima)
        if (!validaData(ini, fim, prods)) {
            session.setAttribute("erro", mensagemErro[6]);
            return "/admin/admin_monta_relatorio_qt_passo_quatro.jsp";
        }



        TipoAnimal unicoTipoAnimalMarcado = null;
        //se não foi marcado o booleano recebe falso e guardamos o tipo marcado no objeto tAnimal
        if (!tipoAnimal.equalsIgnoreCase("todos")) {
            unicoTipoAnimalMarcado = new TipoAnimalService().getTipoAnimalById(Long.parseLong(tipoAnimal));
        }


        //dividir o periodo dado em meses
        List<Date> mesesDescartes = this.getMeses(ini, fim);


        //valores do relatório que será exibe no inicio, dados gerais
        List<String> filtros = new ArrayList<String>();
        List<Integer> dados = new ArrayList<Integer>();
        List<String> seriesGrafico = new ArrayList<String>();
        List<Date> datasGrafico = new ArrayList<Date>();

        int somaMacho = 0;
        int somaFemeas = 0;
        RelatorioResult r = null;
        RelatorioDescarteResult res = null;
        int contraladorPosiciaoFiltroDado = 0;
        for (Date mes : mesesDescartes) {
            res = new RelatorioDescarteResult();
            res.setMes(mes);
            somaMacho = somaFemeas = 0;
            //para cada mês do intervalo caluloa previsão de todos os Produtores e adiciono no result
            for (Produtor p : prods) {

                if (machos != null) {
                    if (unicoTipoAnimalMarcado == null) {
                        for (TipoAnimal tipo : new TipoAnimalService().getAllTiposAnimais()) {
                            somaMacho += getDescarteMachos(p, mes, tipo, res);
                        }
                    } else {
                        somaMacho += getDescarteMachos(p, mes, unicoTipoAnimalMarcado, res);
                    }
                }
                if (femeas != null) {
                    if (unicoTipoAnimalMarcado == null) {
                        for (TipoAnimal tipo : new TipoAnimalService().getAllTiposAnimais()) {
                            somaFemeas += getDescarteFemeas(p, mes, tipo, res);
                        }
                    } else {
                        tipoAnimal = unicoTipoAnimalMarcado.getTipo();
                        somaFemeas += getDescarteFemeas(p, mes, unicoTipoAnimalMarcado, res);
                    }
                }

            }
            if (somaFemeas != 0) {
                filtros.add(contraladorPosiciaoFiltroDado, "Previsão de Descartes de Fêmeas para " + UtilAdrs.treatToMonthYearString(mes));
                seriesGrafico.add(contraladorPosiciaoFiltroDado, "Descarte de Fêmeas");
                datasGrafico.add(contraladorPosiciaoFiltroDado, mes);
                dados.add(contraladorPosiciaoFiltroDado++, somaFemeas);

            }
            if (somaMacho != 0) {
                filtros.add(contraladorPosiciaoFiltroDado, "Previsão de Descartes de Machos para " + UtilAdrs.treatToMonthYearString(mes));
                seriesGrafico.add(contraladorPosiciaoFiltroDado, "Descarte de Machos");
                datasGrafico.add(contraladorPosiciaoFiltroDado, mes);
                dados.add(contraladorPosiciaoFiltroDado++, somaMacho);
            }
            resultDescarte.add(res);
        }

        filtros.add(contraladorPosiciaoFiltroDado, "Previsão total de descartes para " + UtilAdrs.treatToMonthYearString(ini) + " a " + UtilAdrs.treatToMonthYearString(fim));
        dados.add(contraladorPosiciaoFiltroDado++, this.somarValorTotalDescartes(dados));

        //Exibir qual periodo foi marcado
        String periodo = "de " + dataIni + " a " + dataFim;


        //soma os valores individuais dos produtores


        //setar valores na sessão
        session.setAttribute("periodo", periodo);
        session.setAttribute("descartesResult", resultDescarte);
        session.setAttribute("tipoAnimal", tipoAnimal);
        session.setAttribute("somaTotal", dados);
        session.setAttribute("filtros", filtros);
        session.setAttribute("seriesGrafico", seriesGrafico);
        session.setAttribute("datasGrafico", datasGrafico);

        session.setAttribute("detalharRelatorioDescartes", exibirRelatorioDetalhadoDescartes);

        return "/admin/relatorio_qt_gerado_descartes.jsp";



    }

    private int validaCampos(String tipoAnimal, String dataIni, String dataFim, String machos, String femeas) {
        if (tipoAnimal == null || tipoAnimal.trim().isEmpty()) {
            return -1;
        }
        if (((dataFim == null || dataFim.trim().isEmpty()) || (dataIni == null || dataIni.trim().isEmpty()))) {
            return -2;
        }
        if (!UtilAdrs.validaData(dataIni)) {
            return -3;
        }
        if (!UtilAdrs.validaData(dataFim)) {
            return -4;
        }
        if (machos == null && femeas == null) {
            return -5;
        }
        return 1;
    }
    /*Método que verifica se há visitas no período marcado*/

    private boolean validaData(Date ini, Date fim, ArrayList<Produtor> prods) {

        if (ini == null || fim == null) {
            return false;
        }
        if (ini.after(fim)) {
            return false;
        }
        for (Produtor p : prods) {
            List<Visita> visitas = p.getVisitas();
            for (Visita a : visitas) {
                if (a.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                Date visi = a.getData();
                if ((visi.before(fim) || visi.equals(fim)) && (visi.after(ini) || visi.equals(ini))) {
                    return true;
                }
            }
        }
        return false;
    }

    List<Date> getMeses(Date ini, Date fim) {

        List<Date> datas = new ArrayList<Date>();

        for (Date i = ini; (i.before(fim) || i.equals(fim)); i = UtilAdrs.getMesPosterior(i)) {
            datas.add(i);
        }
        return datas;
    }

    int getDescarteMachos(Produtor prod, Date data, TipoAnimal tAnimal, RelatorioDescarteResult r) {

        int limiteMaxBusca = 1;
        for (Date ini = data; limiteMaxBusca <= 6; ini = UtilAdrs.getMesAnterior(ini)) {
            List<Visita> visitas = prod.getVisitasComQuantitativoDescarteNoMes(ini);
            for (Visita v : visitas) {
                QuestionarioQuantitativo qt = v.getQuestionarioQuantitativo();
                Descarte d = qt.buscaDescarteDoTipo(tAnimal, Descarte.SEXO_MACHO, limiteMaxBusca);
                if (d != null) {
                    r.addInformacaoAoRelatorio(prod, d.getQuantidade(), "MACHO");
                    return d.getQuantidade();
                }
            }
            limiteMaxBusca++;
        }
        return 0;
    }

    int getDescarteFemeas(Produtor prod, Date data, TipoAnimal tAnimal, RelatorioDescarteResult r) {
        int limiteMaxBusca = 1;
        for (Date ini = data; limiteMaxBusca <= 6; ini = UtilAdrs.getMesAnterior(ini)) {
            List<Visita> visitas = prod.getVisitasComQuantitativoDescarteNoMes(ini);
            for (Visita v : visitas) {
                QuestionarioQuantitativo qt = v.getQuestionarioQuantitativo();
                Descarte d = qt.buscaDescarteDoTipo(tAnimal, Descarte.SEXO_FEMEA, limiteMaxBusca);
                if (d != null) {
                    r.addInformacaoAoRelatorio(prod, d.getQuantidade(), "FÊMEAS");
                    return d.getQuantidade();
                }
            }
            limiteMaxBusca++;
        }
        return 0;
    }

    int somarValorTotalDescartes(List<Integer> dados) {
        int soma = 0;
        for (Integer i : dados) {
            soma += i;
        }
        return soma;
    }
}
